package com.ruoyi.common.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ruoyi.common.core.domain.CmdResult;

public class BashUtils {

	private static final Logger log = LoggerFactory.getLogger(BashUtils.class);

	public static final Integer SUCCESS_CODE = 0;

	/**
	 * 执行命令
	 *
	 * @param command
	 * @return
	 * @throws IOException
	 * @throws InterruptedException
	 */
	public static CmdResult execCommand(String command, String dir) throws IOException, InterruptedException {
		String[] commands = {"bash","-c",command};
//		String[] commands = command.split(" ");
		List<String> commandList = new ArrayList<>(commands.length);
		ExecutorService executor = Executors.newSingleThreadExecutor();
		StringBuffer result = new StringBuffer();
		StringBuffer resultError = new StringBuffer();
		CmdResult resultCmdResult;
		for (String s : commands) {
			if (StringUtils.isBlank(s)) {
				continue;
			}
			commandList.add(s);
		}
//		commands = new String[commandList.size()];
//		commands = commandList.toArray(commands);
		ProcessBuilder processBuilder = new ProcessBuilder(commands);
		if (StringUtils.isNotBlank(dir)) {
			processBuilder.directory(new File(dir));
		}
		log.info("开始执行命令: {} ", command);
		Process exec = processBuilder.start();
		// 获取外部程序标准输出流
		OutputHandlerCallable callableInputStream = new OutputHandlerCallable(exec.getInputStream());
		OutputHandlerCallable callableErrorStream = new OutputHandlerCallable(exec.getErrorStream());
		Future<StringBuffer> futureInputStream = executor.submit(callableInputStream);
		Future<StringBuffer> futureErrorStream = executor.submit(callableErrorStream);
		try {
			// 获取Callable任务的结果
			System.out.println("等待任务执行结果");
			result = futureInputStream.get();
			System.out.println("等待任务执行错误信息");
			resultError = futureErrorStream.get();
			System.out.println("执行结果为:" + result);
			System.out.println("执行错误信息为:" + resultError);
		} catch (InterruptedException | ExecutionException e) {
			e.printStackTrace();
		} finally {
			// 关闭ExecutorService
			executor.shutdown();
		}
		System.out.println("等待子进程结束");
		int code = exec.waitFor();
		log.info("命令: {} 返回code: {} 返回结果: {}", command, code, result.toString() + ' ' + resultError.toString());
		resultCmdResult = new CmdResult(code, result.toString(), resultError.toString());
		return resultCmdResult;

	}

	/*
	 * 
	 * 单独线程获取输出结果
	 * 
	 */
	private static class OutputHandlerCallable implements Callable<StringBuffer> {
		private InputStream in;

		public OutputHandlerCallable(InputStream in) {
			this.in = in;
		}

		@Override
		public StringBuffer call() {
			StringBuffer sb = new StringBuffer();
			try (BufferedReader bufr = new BufferedReader(new InputStreamReader(this.in))) {
				String line = null;
//				Threads.sleep(10000);
				while ((line = bufr.readLine()) != null) {
//					System.out.println(line);
					sb.append(line).append("\n");
				}

			} catch (IOException e) {
				e.printStackTrace();
			}
			return sb;
		}
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try {
			CmdResult cmdResult = BashUtils.execCommand("java --version", "D:\\360se");
		} catch (IOException | InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}
